const players = require("./module/PlayerData").players;
const Decks = require("./module/Desks");
const Types = require("./module/Types");
const ActorPlayingState = Types.ActorPlayingState;
const Fsm = require("./module/game-fsm");

const Game = cc.Class({
    extends: cc.Component,

    properties: {
        playerAnchors: {
            type: cc.Node,
            default: [],
        },
        playerPrefab: cc.Prefab,
        dealer: cc.Node,
        inGameUI: cc.Node,
        betUI: cc.Node,
        assetMng: cc.Node,
        audioMng: cc.Node,
        turnDuration: 0,
        betDuration: 0,
        totalChipsNum: 0,
        totalDiamondNum: 0,
        numberOfDecks: {
            default: 1,
            type: cc.Integer,
        }
    },

    statics: {
        // 变量,表示自己
        instance: null
    },
    onLoad () {
        cc.log("loading game scene");
        Game.instance = this;
        this.inGameUI = this.inGameUI.getComponent("InGameUI");
        this.inGameUI.init(this.betDuration);
        this.assetMng = this.assetMng.getComponent("AssetMng");
        // TODO add audio ui
        // this.audioMng = this.audioMng.getComponent("AudioMng");
        this.betUI = this.betUI.getComponent("Bet");
        this.betUI.init();

        // 庄家
        this.dealer = this.dealer.getComponent("Dealer");
        this.dealer.init();

        this.player = null;
        this.createPlayers();

        this.info = this.inGameUI.resultTxt;
        this.totalChips = this.inGameUI.labelTotalChips;

        // init logic
        this.decks = new Decks(this.numberOfDecks);
        this.fsm = Fsm;
        this.fsm.init(this);
        // TODO add fsm callback

        // start
        this.updateTotalChips();

        // TODO play music
        // this.audioMng.playMusic();
    },

    // 添加筹码
    addStake: function(delta) {
        if (this.totalChipsNum < delta) {
            cc.log('not enough chips');
            this.info.enabled = true;
            this.info.string = '金币不足';
            return false;
        } else {
            cc.log('add stake, delta = ', delta);
            this.totalChipsNum -= delta;
            this.updateTotalChips();
            this.player.addStake(delta);
            // TODO play audio
            // this.audioMng.playChips();
            this.info.enabled = false;
            this.info.string = '请下注';
            return true;
        }
    },

    resetStake: function() {
        this.totalChipsNum += this.player.stakeNum;
        this.player.resetStake();
        this.updateTotalChips();
    },

    // 更新总数
    updateTotalChips: function() {
        this.totalChips.string = this.totalChipsNum;
        this.player.renderer.updateTotalStake(this.totalChipsNum);
    },

    // 生成 5 个玩家
    createPlayers: function() {
        for (let i = 0; i < 5; ++i) {
            const playerNode = cc.instantiate(this.playerPrefab);
            const anchor = this.playerAnchors[i];
            // 翻转位置
            const switchSide = i > 2;
            anchor.addChild(playerNode);
            playerNode.position = cc.v2(0, 0);
            const playerInfoPos = anchor.getChildByName("anchorPlayerInfo").getPosition();
            const stakePos = anchor.getChildByName("anchorStake").getPosition();
            const actorRenderer = playerNode.getComponent("ActorRenderer");
            actorRenderer.init(players[i], playerInfoPos, stakePos, this.turnDuration, switchSide);
            if (i === 2) {
                this.player = playerNode.getComponent("Player");
                this.player.init();
            }
        }
    },

    // ui 事件回调
    // 要牌
    hit: function () {
        this.player.addCard(this.decks.draw());
        if (this.player.state === ActorPlayingState.Bust) {
            this.fsm.onPlayerActed();
        }
        // TODO play audio
        // this.audioMng.playCard();
        // this.audioMng.playButton();
    },

    // 玩家停牌
    stand: function () {
        this.player.stand();
        // TODO play button
        // this.audioMng.playButton();
        this.fsm.onPlayerActed();
    },

    deal: function () {
        this.fsm.toDeal();
        // TODO play button
        // this.audioMng.playButton();
    },

    start: function () {
        this.fsm.toBet();
        // TODO play button
        // this.audioMng.playButton();
    },

    // 玩家报到
    report: function () {
        this.player.report();
        this.fsm.onPlayerActed();
    },

    quitToMenu: function () {
        cc.director.loadScene('menu');
    },

    // fsm 回调

    // 21点玩法
    onEnterDealState: function () {
        cc.log('发牌 2 张');
        this.betUI.resetTossedChips();
        this.inGameUI.resetCountDown();
        this.player.renderer.showStakeChips(this.player.stakeNum);
        // 发牌
        this.player.addCard(this.decks.draw());
        const holdCard = this.decks.draw();
        this.dealer.addHoleCard(holdCard);
        this.player.addCard(this.decks.draw());
        this.dealer.addCard(this.decks.draw());
        // TODO play audio
        // this.audioMng.playCard();
        this.fsm.onDealed();
    },

    // 轮到玩家
    onPlayersTurnState: function(enter) {
        if (enter) {
            this.inGameUI.showGameState();
        }
    },

    onEnterDealersTurnState: function() {
        while (this.dealer.state === ActorPlayingState.Normal) {
            if (this.dealer.wantHit()) {
                this.dealer.addCard(this.decks.draw());
            } else {
                this.dealer.stand();
            }
        }
        // 结束
        this.fsm.onDealerActed();
    },

    onEndState: function(enter) {
        cc.log('end state');
        this.info.enabled = enter;
        if (!enter) {
            return;
        }
        this.dealer.revealHoldCard();
        this.inGameUI.showResultState();
        const outcome = this._getPlayerResult(this.player, this.dealer);
        switch (outcome) {
            case Types.Outcome.Win:
                this.info.string = 'You Win';
                // TODO play music
                // this.audioMng.pauseMusic();
                // this.audioMng.playWin();
                // 拿回原先自己的筹码
                this.totalChipsNum += this.player.stakeNum;
                // 奖励筹码
                let winChipsNum = this.player.stakeNum;
                if (!this.player.state === Types.ActorPlayingState.Report) {
                    if (this.player.hand === Types.Hand.BlackJack) {
                        winChipsNum *= 1.5;
                    } else {
                        // 五小龙
                        winChipsNum *= 2;
                    }
                }
                this.totalChipsNum += winChipsNum;
                this.updateTotalChips();
                break;
            case Types.Outcome.Lose:
                this.info.string = 'You Lose';
                // TODO play music
                // this.audioMng.pauseMusic();
                // this.audioMng.playLose();
                break;
            case Types.Outcome.Tie:
                this.info.string = 'Draw';
                // 退还筹码
                this.totalChipsNum += this.player.stakeNum;
                this.updateTotalChips();
                break;
        }
    },

    // 开始赌博
    onBetState: function (isEnter) {
        cc.log('start betting');
        if (isEnter) {
            this.decks.reset();
            this.player.reset();
            this.dealer.reset();
            this.info.string = '请下注';
            this.inGameUI.showBetState();
            this.inGameUI.startCountDown();
            // TODO play audio
            // this.audioMng.resumeMusic();
        }
        this.info.enabled = isEnter;
    },


    // private results
    _getPlayerResult: function (player, dealer) {
        const Outcome = Types.Outcome;
        if (player.state === ActorPlayingState.Bust) {
            // 输了
            return Outcome.Lose;
        } else if (dealer.state === ActorPlayingState.Bust) {
            return Outcome.Win;
        } else {
            if (player.state === ActorPlayingState.Report) {
                return Outcome.Win;
            } else {
                // 比较牌型
                if (player.hand > dealer.hand) {
                    return Outcome.Win;
                } else if (player.hand < dealer.hand) {
                    return Outcome.Lose;
                } else {
                    // 牌型一样, 比较分数
                    if (player.bestPoint === dealer.bestPoint) {
                        return Outcome.Tie;
                    } else if (player.bestPoint < dealer.bestPoint) {
                        return Outcome.Lose;
                    } else {
                        return Outcome.Win;
                    }
                }
            }
        }

    }

});
